<?php
/**
 * Created by PhpStorm.
 * User: 牛赞赞
 * Date: 2020/12/30
 * Time: 16:20
 */

namespace App\Game\Logic;


use App\Game\Conf\GameProgress;
use App\Game\Conf\SubCmd;
use App\Game\Core\AStrategy;
use App\Game\Core\Djs;
use App\Game\Core\Message;
use App\Game\Core\Robot;
use App\Game\Core\Room;
use App\Model\User;
use App\Service\GrandMatchService;
use App\Task\GameSyncTask;

class GrandMatchPull extends AStrategy
{
    /**
     * 将用户拉进正在进行游戏
     */
    public function exec()
    {
        $game_conf = $this->game_conf;
        $account = $this->_params['userinfo']['account'];
        $user_map_key = sprintf($game_conf['user_room'], $account);
        $room_no = '';
        if (redis()->exists($user_map_key)) {
            $room_no = redis()->get($user_map_key);
        }
        if ($room_no) {
            ddNode('gp7');
            $timer = Room::getRoomData($room_no, 'timer');
            if (!empty($timer)) {
                //查看定时器工作状态，如果已经很久没动过，表明该房间已卡死，此时强制踢出所有用户
                $timer = json_decode($timer, true);
                $now = time();
                $gameTime = strtotime($timer['time']);
                if ($now - $gameTime > 20) {
                    pushForceQuitMsg($room_no, $account);
                    return;
                }
            }
        }
        $playerInfo = Djs::getDjsPlayerData($account);
//        $left_time = $playerInfo['end_time'] - time();
        ddNode('gp1');
        $type = $playerInfo['progress'];
        if ($type == Djs::$progress_game_over) { //结算阶段

            ddNode('gp2');
            $data['type'] = Djs::$progress_game_over;
            $data['info'] = [];
            $data['info']['curr_prize'] = [];
            $data['info']['next_prize'] = [];
            $data['info']['pre_prize'] = [];
            if (!empty($playerInfo)) {

                if ($playerInfo['status'] == 0) {
                    $round_num = $playerInfo['stage'] - 1;
                    ddNode('gp3');
                    // 下局奖励
                    if ($playerInfo['stage'] == 1) {
                        ddNode('gp4');
                        $curr_prize = GrandMatchService::getRoundPrize($round_num);
                        $data['info']['next_prize'] = GrandMatchService::showPrize($curr_prize);
                    } else {
                        ddNode('gp5');
                        $next_prize = GrandMatchService::getNextStagePrize($round_num);
                        $data['info']['next_prize'] = GrandMatchService::showPrize($next_prize);
                    }
                    // 上局奖励查询
                    $pre_prize = GrandMatchService::getPreStagePrize($round_num);
                    $data['info']['pre_prize'] = GrandMatchService::showPrize($pre_prize);
                    $round_num += 1;
                }
                if ($playerInfo['status'] == 1) {
                    $round_num = $playerInfo['stage'];
                    ddNode('gp6');
                    $curr_prize = GrandMatchService::getRoundPrize($round_num);
                    $data['info']['curr_prize'] = GrandMatchService::showPrize($curr_prize);
//                    dd('curr_prize', $curr_prize);
//                    dd('curr_prize2', $data['info']['curr_prize']);
                    // 下局奖励
                    $next_prize = GrandMatchService::getNextStagePrize($round_num);
                    $data['info']['next_prize'] = GrandMatchService::showPrize($next_prize);
                }
                $data['info']['stage'] = $round_num;
                $data['info']['turn'] = $playerInfo['turn'];
                $data['info']['start_time'] = $playerInfo['start_time'];
                $data['info']['alive'] = $playerInfo['alive'];
                $data['info']['status'] = $playerInfo['status'];
            }
            Message::pushDataToUser($account, $data, SubCmd::GAME_DJS_PULL_RESP);
            return;
        }


        if ($type == Djs::$progress_game_match) {
//            sleep(2);
            $playerInfo = Djs::getDjsPlayerData($account);
            ddNode('gp7.5');
            $type = $playerInfo['progress'];
        }


        if ($type == Djs::$progress_game_match) { //匹配中
            ddNode('gp8');
            $data['status'] = 'success';
            $data['type'] = Djs::$progress_game_match;

            if (!$room_no) {
                $room_no = Room::createRoomNo();
            }
            $uinfo = User::userInfo($account);
            $chairs = Room::getRoomChairs($room_no);
            if (count($chairs) < 4 && !isset($chairs[$account])) {
                Room::addRoomWait($room_no, $account);
                Room::addRoomChair($account, $room_no);
            }
            $chairs = Room::getRoomChairs($room_no);
            $data['info'] = [
                ["account" => $uinfo['account'],
                    "avatar" => $uinfo['avatar'],
                    "nickname" => filterNickname($uinfo['nickname']),
                    "score" => (int)$uinfo['score'],
                    "chair_id" => (int)$chairs[$account],
                    "prepare" => 0,
                    "stage" => (int)$playerInfo['stage'],
                    "start_time" => $playerInfo['start_time']],
            ];
            Message::pushDataToUser($account, $data, SubCmd::GAME_DJS_PULL_RESP);

            if (count($chairs) < 4) {
                sleep(2);
                Robot::addSingleDjsRobot($room_no);
            }
            if (count($chairs) == 4) {
                $gp = getGameProgress($room_no);
                if (!$gp) {
//                    sleep(2);
                    //满员
                    $players = Djs::initMatchData($room_no);
                    $msg = [
                        'status' => 'success',
                        'room_no' => $room_no,
                        'players' => $players
                    ];
                    Message::broadcast($room_no, $msg, SubCmd::GAME_QUICK_MATCH, 1);
                    Djs::removeWaitRoom($room_no);
                    setGameProgress($room_no, GameProgress::GAME_PREPARE);
                }
                if ($gp == GameProgress::GAME_PREPARE) {
                    playerGamePrepare($room_no, $account);
                    $playerInfo['progress'] = Djs::$progress_game_prepare;
                    Djs::updatePlayerData($account, $playerInfo);
                    $waiters = Room::getRoomWait($room_no);
                    $chairs = Room::getRoomChairs($room_no);
                    $chair_id = $chairs[$account];
                    //发送准备消息
                    $msg = ['status' => 0, 'chair_id' => $chair_id, 'master' => 0];
                    Message::broadcast($room_no, $msg, SubCmd::SUB_GAME_PREPARE_RESP);
                    foreach ($waiters as $acc) {
                        if (Robot::isRobot($room_no, $acc)) {
                            $prepare = getGamePrepare($room_no, $acc);
                            if (!$prepare) {
                                playerGamePrepare($room_no, $acc);
                                $chair_id = $chairs[$acc];
                                //发送准备消息
                                $msg = ['status' => 0, 'chair_id' => $chair_id, 'master' => 0];
                                Message::broadcast($room_no, $msg, SubCmd::SUB_GAME_PREPARE_RESP);
                                sleep(rand(1, 2));
                            }
                            continue;
                        }
                        $playerInfo = Djs::getDjsPlayerData($acc);
                        $playerInfo['progress'] = Djs::$progress_game_prepare;
                        Djs::updatePlayerData($acc, $playerInfo);
                    }
//                    sleep(2);
                    $prepares = getGamePrepareALL($room_no);
                    if (count($prepares) == 4) {
                        setGameProgress($room_no, GameProgress::GAME_CHANGE_CARD);
                        $master = rand(1, 4);
                        $msg = ['status' => 0, 'chair_id' => $chair_id, 'master' => $master];
                        Message::broadCast($room_no, $msg, SubCmd::SUB_GAME_PREPARE_RESP, 1);
                        //发牌
                        $task = container()->get(GameSyncTask::class);
                        $task->assignCards($room_no, $master);
                    }
                }
            }
            return;
        }

        if ($type == Djs::$progress_game_prepare) { //准备阶段
            ddNode('gp9');
            $matchPlayers = [];
            $prepareArr = getGamePrepareALL($room_no);
            $chairs = getRoomChairs($room_no);
            foreach ($chairs as $acc => $cid) {
                $uinfo = User::userInfo($acc);
                $is_robot = Robot::isRobot($room_no, $acc);
                if ($is_robot) {
                    $score = Robot::getRoomRobot($room_no, $acc);
                } else {
                    $score = $uinfo['score'];
                }
                $djsInfo = Djs::getDjsPlayerData($acc);
                $matchPlayers[] = [
                    "account" => $uinfo['account'],
                    "avatar" => $uinfo['avatar'],
                    "nickname" => filterNickname($uinfo['nickname']),
                    "score" => (int)$score,
                    "chair_id" => (int)$cid,
                    "prepare" => isset($prepareArr[$acc]) ? 1 : 0,
                    "stage" => (int)$djsInfo['stage'],
                    "start_time" => $djsInfo['start_time'],
                ];
            }
            $data['status'] = 'success';
            $data['type'] = Djs::$progress_game_prepare;
            $data['info'] = $matchPlayers;
            Message::pushDataToUser($account, $data, SubCmd::GAME_DJS_PULL_RESP);

            playerGamePrepare($room_no, $account);
            $playerInfo['progress'] = Djs::$progress_game_prepare;
            Djs::updatePlayerData($account, $playerInfo);
            $waiters = Room::getRoomWait($room_no);
            $chairs = Room::getRoomChairs($room_no);
            $chair_id = $chairs[$account];
            //发送准备消息
            $msg = ['status' => 0, 'chair_id' => $chair_id, 'master' => 0];
            Message::broadcast($room_no, $msg, SubCmd::SUB_GAME_PREPARE_RESP);
            foreach ($waiters as $acc) {
                if (Robot::isRobot($room_no, $acc)) {
                    $prepare = getGamePrepare($room_no, $acc);
                    if (!$prepare) {
                        playerGamePrepare($room_no, $acc);
                        $chair_id = $chairs[$acc];
                        //发送准备消息
                        $msg = ['status' => 0, 'chair_id' => $chair_id, 'master' => 0];
                        Message::broadcast($room_no, $msg, SubCmd::SUB_GAME_PREPARE_RESP);
                        sleep(rand(1, 2));
                    }
                    continue;
                }
                $playerInfo = Djs::getDjsPlayerData($acc);
                $playerInfo['progress'] = Djs::$progress_game_prepare;
                Djs::updatePlayerData($acc, $playerInfo);
            }
            sleep(2);
            $prepares = getGamePrepareALL($room_no);
            if (count($prepares) == 4) {
                setGameProgress($room_no, GameProgress::GAME_CHANGE_CARD);
                $master = rand(1, 4);
                $msg = ['status' => 0, 'chair_id' => $chair_id, 'master' => $master];
                Message::broadCast($room_no, $msg, SubCmd::SUB_GAME_PREPARE_RESP, 1);
                //发牌
                $task = container()->get(GameSyncTask::class);
                $task->assignCards($room_no, $master);
            }

            return;
        }

        //先设置玩家掉线状态
        playerOffline($room_no, $account);
        $chair_id = getChairIdbyAccount($room_no, $account);
        $waitArr = [$chair_id];
        while (true) {
            $progress = getGameProgress($room_no);
            if (!in_array($progress, [GameProgress::GAME_JOIN, GameProgress::GAME_PREPARE,
                GameProgress::GAME_CACULAR])) {
                $room_data = getRoomData($room_no);

                if (in_array($progress, [GameProgress::GAME_OUT_CARD, GameProgress::GAME_CHECK_HPG])) {
                    if (in_array($room_data['next_chair_id'], $waitArr)) {
                        continue;
                    }
                }
                $djsInfo = Djs::getDjsPlayerData($account);

                $user_room_data = json_decode($room_data[$account], true);
                $user_data['type'] = Djs::$progress_game_start;
                $user_data['stage'] = (int)$djsInfo['stage'];
                $user_data['start_time'] = (int)$djsInfo['start_time'];
                $user_data['chair_id'] = $user_room_data['chair_id'];
                $user_data['master'] = (int)$room_data['master'];
                $user_data['take_over'] = $user_room_data['take_over'];
                $hand = json_decode($room_data['hand'], true);
                $user_data['hand_num'] = count($hand);
                $room_data = getRoomData($room_no);
                $user_data['room_data'] = $this->roomData($room_data);
                $user_data['play'] = [
                    'last_chair_id' => $room_data['last_chair_id'],
                    'next_chair_id' => $room_data['next_chair_id']
                ];
                playerOnline($room_no, $account);

                $data['status'] = 'success';
                $data['type'] = Djs::$progress_game_start;
                $data['info'] = $user_data;

                Message::pushDataToPlayer($account, $data, SubCmd::GAME_DJS_PULL_RESP);
                dd('掉线重连信息', $user_data);
                break;
            }

            $prepareArr = getGamePrepareALL($room_no);
            if ($prepareArr < 4) {
                pushForceQuitMsg($room_no, $account);
                clearRoomDataAll($room_no);
                break;
            }
            $offlinePlayers = [];
            foreach ($prepareArr as $acc => $status) {
                if ($status == GameProgress::USER_OFFLINE) {
                    $offlinePlayers[] = $acc;
                }
            }
            if (count($offlinePlayers) == 4) {
                pushForceQuitMsg($room_no, $account);
                clearRoomDataAll($room_no);
                break;
            }
            sleep(1);
        }
    }


    /**
     * 组装房间玩家牌局数据
     * @param $room_data
     * @return array
     */

    protected
    function roomData($room_data)
    {
        $user_info = json_decode($room_data['uinfo'], true);
        $uidArr = [];
        foreach ($user_info as $k => $v) {
            $uidArr[] = $k;
        }
        // 查询用户信息
        $users = User::getUsers($uidArr);
        $return_data = [];
        $room_no = $room_data['room_no'];
        $colors = getRoomColors($room_no);
        foreach ($users['data'] as $ks => $vs) {
            $user_data = json_decode($room_data[$vs['account']], true);
            $pinfo = Djs::getDjsPlayerData($vs['account']);
            $return_data[] = [
                'stage' => $pinfo ? $pinfo['stage'] : 1,
                'start_time' => $pinfo ? $pinfo['start_time'] : time(),
                'card' => $user_data['card'],
                'peng' => $user_data['peng'],
                'gang' => $user_data['gang'],
                'hu' => $user_data['hu'],
                'out_card' => $user_data['out_card'],
                'chair_id' => (int)$user_data['chair_id'],
                'take_over' => (int)$user_data['take_over'],
                'avatar' => $vs['avatar'],
                'nickname' => filterNickname($vs['nickname']),
                'score' => intval($user_info[$vs['account']]['total_score']),
                'que' => isset($colors[$user_data['chair_id']]) ? $colors[$user_data['chair_id']] : 0,
            ];
        }
        return $return_data;
    }

}
